package com.earthea.application.task.mysql;

import cn.hutool.core.util.IdUtil;
import com.earthea.application.mapper.TaskMapper;
import com.earthea.application.task.entity.Task;
import com.earthea.application.task.entity.TaskStatus;
import com.earthea.common.util.IpUtils;
import com.google.common.base.Preconditions;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Repository
public class TaskRepository {

    @Autowired
    private TaskMapper taskMapper;

    public int batchAddTask(List<Task> tasks) {
        tasks = check(tasks);
        if (CollectionUtils.isEmpty(tasks)) {
            return 0;
        }
        for (Task task : tasks) {
            if (StringUtils.isBlank(task.getTaskId())) {
                task.setTaskId(IdUtil.fastSimpleUUID());
            }
            if (task.getData() == null) {
                task.setData(StringUtils.EMPTY);
            }
        }
        return taskMapper.batchAdd(Task.getTableName(), tasks);
    }

    public List<Task> poll(String type, String label, int status, int limit) {
        Preconditions.checkArgument(limit > 0, "limit must be greater than 0");
        return taskMapper.query(Task.getTableName(), type, label, status, limit);
    }

    public List<Task> queryByHistory(int limit) {
        Preconditions.checkArgument(limit > 0, "limit must be greater than 0");
        return taskMapper.queryByHistory(Task.getTableName(), limit);
    }

    public int batchUpdateTask(List<Task> tasks) {
        tasks = check(tasks);
        if (CollectionUtils.isEmpty(tasks)) {
            return 0;
        }
        for (Task task : tasks) {
            if (task.getStatus() == TaskStatus.FAIL.getStatus()) {
                if (task.getRetry() < task.getMaxRetry()) {
                    task.setRetry(task.getRetry() + 1);
                    task.setStatus(TaskStatus.INIT.getStatus());
                }
            }
        }
        return taskMapper.batchUpdateTask(Task.getTableName(), tasks);
    }

    public int batchUpdateToProcessing(List<Task> tasks) {
        tasks = check(tasks);
        if (CollectionUtils.isEmpty(tasks)) {
            return 0;
        }
        return taskMapper.batchUpdateToProcessing(Task.getTableName(), tasks, IpUtils.getLocalIp());
    }

    public int batchUpdateProcessing(String updateTime, int limit) {
        Preconditions.checkArgument(limit > 0, "limit must be greater than 0");
        return taskMapper.batchUpdateProcessing(Task.getTableName(), updateTime, limit);
    }

    public int batchDelete(List<Task> tasks) {
        tasks = check(tasks);
        if (CollectionUtils.isEmpty(tasks)) {
            return 0;
        }
        return taskMapper.batchDelete(Task.getTableName(), tasks);
    }

    public int batchAddHistory(List<Task> tasks) {
        tasks = check(tasks);
        if (CollectionUtils.isEmpty(tasks)) {
            return 0;
        }
        return tasks.stream().collect(Collectors.groupingBy(Task::getHistoryTableName)).entrySet().stream().mapToInt(entry -> taskMapper.batchAddHistory(entry.getKey(), entry.getValue())).sum();
    }

    public void create() {
        taskMapper.create(Task.getTableName());
    }

    public void createHistory(String tableName) {
        taskMapper.createHistory(tableName);
    }

    private List<Task> check(List<Task> tasks) {
        return Optional.ofNullable(tasks).orElse(Collections.emptyList()).stream().filter(Objects::nonNull).collect(Collectors.toList());
    }

}
